﻿package bdz.projects.lavender.opsm.ui {
	
	import bdz.projects.lavender.opsm.events.FlipGridEvent;
	import bdz.projects.lavender.opsm.model.FlipCollection;
	import bdz.projects.lavender.opsm.events.FlipBoxEvent;
	import bdz.projects.lavender.opsm.vo.ProductVO;
	import bdz.common.events.GenericEvent;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.BevelFilter;
	import flash.filters.DropShadowFilter;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.*;
	import com.greensock.easing.*;
	/**
	 * ...
	 * @author Donald
	 */
	public class FlipGrid extends MovieClip {
		
		private var _baseW:Number = 360;
		private var _baseH:Number = 180;
		private var _gridRef:Array;
		private var _guide:DisplayGrid;
		private var _pagingRef:Array;
		private var _pagingrendered:Boolean = false;
		private var _rendered:Boolean = false;
		private var cnt:Number = 0;
		private var _completed:Number = 0;
		private var _initcreation:Boolean = true;
		private var _scaleMultiplier:Number = .33333;
		private var _detailsGuide:ProductDetailedView;
		private var _onDetail:Boolean = false;
		public static var FLIPPED_FILTER:String = "filter";
		public static var FLIPPED_PAGE:String = "page";
		public static var FLIPPED_DETAILS:String = "details";
		public function FlipGrid(dw:Number = -1, dh:Number = -1, scale:Number = .33333) {
			_scaleMultiplier = scale;
			if (dw != -1 && dh != -1) {
				_baseW = dw;
				_baseH = dh;
			}
			addEventListener(Event.ADDED_TO_STAGE, initializeComponent);
			mouseEnabled = false;
			super();
		}
		private function initializeComponent(evt:Event):void {
			visible = false;
		}
		
		protected function onGuideRenderProgress(evt:GenericEvent):void {
			showGuide(false);
		}
		protected function hideDetailedGuide(bool:Boolean):void { 
			for each(var fb:FlipBox in _gridRef) {
				fb.visible = !bool;
			}
			for each(fb in _pagingRef) {
				fb.visible = !bool;
			}
		}
		protected function hideBaseGuide(bool:Boolean):void {
			for each(var fb:FlipBox in _gridRef) {
				fb.visible = !bool;
			}
			for each(fb in _pagingRef) {
				fb.visible = bool;
			}
		}
		protected function onGuideRendered(evt:GenericEvent):void {
			
			if (_initcreation) {
				_initcreation = false;
				startRendering();
				startPageChange(false);
			}else{
				if(!evt.data.pageChange){
					startRendering();
				}else {
					startPageChange();
				}
			}
		}
		protected function showDetailedGuide(bool:Boolean):void {
			visible = !bool;
			_detailsGuide.visible = bool;
			if (bool) {
				_detailsGuide.loadThumbnails();
			}
		}
		protected function showGuide(bool:Boolean):void {
			visible = !bool;
			_guide.visible = bool;
		}
		protected function startPageFlip(bmps:Array):void {
			_completed = 0;
			showGuide(false);
			var del:Number = 0;
			var _refCopy:Array = _pagingRef.slice();
			
			while (_refCopy.length) {
				var flip:FlipBox = _refCopy.shift();
				var sp:Sprite = bmps.shift();
				flip.activateFace(sp, del, { ease:Strong.easeInOut, speed:.9, vertical:true } );
				del += 0.03;
			
			}
			bmps = null;
		}
		protected function startRandomFlips(bmps:Array):void {
			
			_completed = 0;
			showGuide(false);
			var del:Number = 0;
			var _refCopy:Array = _gridRef.slice();
			
			while (_refCopy.length) {
				var rand:Number = Math.floor(Math.random() * _refCopy.length);
				var flip:FlipBox = _refCopy.splice(rand, 1)[0];
				flip.activateFace(bmps.splice(rand, 1)[0], del );
				del += 0.02;
			
			}
			bmps = null;
		}
		protected function onBoxFlipPageComplete(evt:FlipBoxEvent):void {
			if (_completed < _guide.origRows - 1) {
				_completed++;
			}else {
				_completed = 0;
				showGuide(true);
				dispatchEvent(new FlipGridEvent(FlipGridEvent.FLIP_DONE, { type:FLIPPED_PAGE } ));
			}
		}
		protected function onBoxFlipComplete(evt:FlipBoxEvent):void {
			if (_completed < _gridRef.length - 1) {
				_completed++;
			}else {
				_completed = 0;
				if (_onDetail) {
					showDetailedGuide(true);
					_onDetail = false;
					dispatchEvent(new FlipGridEvent(FlipGridEvent.FLIP_DONE, { type:FLIPPED_DETAILS } ));
				}else{
					showGuide(true);
					dispatchEvent(new FlipGridEvent(FlipGridEvent.FLIP_DONE, { type:FLIPPED_FILTER } ));
				}
				
			}
			
		}
		protected function startDetailedChange(execute:Boolean = true):void {
			
			if (execute) {
				startPageChange(false);
				hideBaseGuide(false);
			}
			
			
			if(_gridRef == null){
				_gridRef = new Array();
			}
			var bmp:BitmapData = _detailsGuide.bitmap;
			var startx:Number = 0;
			var sx:Number = 0;
			var sy:Number = 0;
			var _gridCopy:Array = _gridRef.slice();
			var _bmps:Array = new Array();
			
			for (var row:int = 0; row < _guide.origRows; row++) {
				for (var col:int = 0; col < _guide.origCols; col++) {
					var fb:FlipBox = _rendered ?  _gridCopy.shift() : new FlipBox();
					var bdata:BitmapData = new BitmapData(Math.ceil(_baseW * _scaleMultiplier), Math.ceil(_baseH * _scaleMultiplier), true, 0x00ffffff);
					if (!_rendered) {
						fb.addEventListener(FlipBoxEvent.TRANSITION_DONE, onBoxFlipComplete);
					}
					/// Draw the pixels on a sprite
					var fbmp:Sprite = new Sprite();
					fbmp.graphics.clear();
					bdata.copyPixels(bmp, new Rectangle(sx, sy, (col || 1) * Math.ceil(_baseW * _scaleMultiplier), (row || 1) * Math.ceil(_baseH * _scaleMultiplier)), new Point(0, 0));
					fbmp.graphics.beginBitmapFill(bdata, null, false, true);
					fbmp.graphics.drawRect(0, 0, Math.ceil(_baseW * _scaleMultiplier), Math.ceil(_baseH * _scaleMultiplier));
					fbmp.graphics.endFill();
					
					///
					fb.x = sx;
					fb.y = sy;
					sx += Math.ceil(_baseW * _scaleMultiplier);
					
					if (_rendered) {
						if (!execute) {
							if (fb.isFrontFacing) {
								fb.front = fbmp;
							}else {
								fb.back = fbmp;
							}
						}
						_bmps.push(fbmp);
					}else {
						fb.front = fbmp;
						_gridRef.push(addChild(fb));
					}
					
				}
				sx = startx;
				sy += Math.ceil(_baseH * _scaleMultiplier);
			}
			
			
			
			
			startRandomFlips(_bmps);
			
			
			_rendered = true;
			_gridCopy = null;
			_bmps = null;
			
			if (stage) {
				stage.invalidate();
			}
		}
		protected function startPageChange(execute:Boolean = true):void {
			if (execute) {
				startRendering(false);
				hideBaseGuide(true);
			}
			if(_pagingRef == null){
				_pagingRef = new Array();
			}
			var bmp:BitmapData = _guide.bitmap;
			
			var sx:Number = (Math.ceil(_baseW * _scaleMultiplier) * Math.ceil(_guide.origCols-1)) * .5;
			var sy:Number = 0;
			var _gridCopy:Array = _pagingRef.slice();
			var _bmps:Array = new Array();
			
			for (var row:int = 0; row < _guide.origRows; row++) {
				var fb:FlipBox = _pagingrendered ?  _gridCopy.shift() : new FlipBox();
				fb.flipOrientation = FlipBox.FLIP_VERTICAL;
				var bdata:BitmapData = new BitmapData(Math.ceil((_baseW * _scaleMultiplier) * _guide.origCols), Math.ceil(_baseH * _scaleMultiplier), true, 0x00ffffff);
				if (!_pagingrendered) {
					fb.addEventListener(FlipBoxEvent.TRANSITION_DONE, onBoxFlipPageComplete);
				}
				/// Draw the pixels on a sprite
				var fbmp:Sprite = new Sprite();
				fbmp.graphics.clear();
				//check to clear here
				
				bdata.copyPixels(bmp, new Rectangle(0, sy, Math.ceil((_baseW * _scaleMultiplier) * _guide.origCols), Math.ceil(_baseH * _scaleMultiplier)), new Point(0, 0));
				fbmp.graphics.beginBitmapFill(bdata, null, false, false);
				fbmp.graphics.drawRect(0, 0, Math.ceil(_baseW * _scaleMultiplier) * _guide.origCols, Math.ceil(_baseH * _scaleMultiplier));
				fbmp.graphics.endFill();
				
				///
				fb.x = sx;
				fb.y = sy;
				sy += Math.ceil(_baseH * _scaleMultiplier);
				
				if (_pagingrendered) {
					if (!execute) {
						if (fb.isFrontFacing) {	
							fb.front = fbmp;
						}else {
							fb.back = fbmp;
						}	
					}
					_bmps.push(fbmp);
				}else {
					fb.front = fbmp;
					_pagingRef.push(addChild(fb));
				}
				
			}
			if(_pagingrendered && _bmps.length && execute){
				startPageFlip(_bmps);
			}
			_pagingrendered = true;
			_gridCopy = null;
			_bmps = null;
			
			if (stage) {
				stage.invalidate();
			}
		}
		protected function startRendering(execute:Boolean = true):void {
			if (execute) {
				startPageChange(false);
				hideBaseGuide(false);
			}
			if(_gridRef == null){
				_gridRef = new Array();
			}
			
			var bmp:BitmapData = _guide.bitmap;
			var startx:Number = 0;
			var sx:Number = 0;
			var sy:Number = 0;
			var _gridCopy:Array = _gridRef.slice();
			var _bmps:Array = new Array();
			
			for (var row:int = 0; row < _guide.origRows; row++) {
				for (var col:int = 0; col < _guide.origCols; col++) {
					var fb:FlipBox = _rendered ?  _gridCopy.shift() : new FlipBox();
					var bdata:BitmapData = new BitmapData(Math.ceil(_baseW * _scaleMultiplier), Math.ceil(_baseH * _scaleMultiplier), true, 0x00ffffff);
					if (!_rendered) {
						fb.addEventListener(FlipBoxEvent.TRANSITION_DONE, onBoxFlipComplete);
					}
					/// Draw the pixels on a sprite
					var fbmp:Sprite = new Sprite();
					fbmp.graphics.clear();
					bdata.copyPixels(bmp, new Rectangle(sx, sy, (col || 1) * Math.ceil(_baseW * _scaleMultiplier), (row || 1) * Math.ceil(_baseH * _scaleMultiplier)), new Point(0, 0));
					fbmp.graphics.beginBitmapFill(bdata, null, false, true);
					fbmp.graphics.drawRect(0, 0, Math.ceil(_baseW * _scaleMultiplier), Math.ceil(_baseH * _scaleMultiplier));
					fbmp.graphics.endFill();
					
					///
					fb.x = sx;
					fb.y = sy;
					sx += Math.ceil(_baseW * _scaleMultiplier);
					
					if (_rendered) {
						if (!execute) {
							if (fb.isFrontFacing) {
								fb.front = fbmp;
							}else {
								fb.back = fbmp;
							}
						}
						_bmps.push(fbmp);
					}else {
						fb.front = fbmp;
						_gridRef.push(addChild(fb));
					}
					
				}
				sx = startx;
				sy += Math.ceil(_baseH * _scaleMultiplier);
			}
			
			//place transitions here.
			if (_rendered &&  _bmps.length && execute) {
				//add something to randomize transitions
				startRandomFlips(_bmps);
			}
			//
			_rendered = true;
			_gridCopy = null;
			_bmps = null;
			
			if (stage) {
				stage.invalidate();
			}
			
		}
		protected function refreshGuideSlices():void {
			
			var bmp:BitmapData = _detailsGuide.bitmap;
			var execute:Boolean = false;
			
			var startx:Number = 0;
			var sx:Number = 0;
			var sy:Number = 0;
			var _gridCopy:Array = _gridRef.slice();
			var _bmps:Array = new Array();
			
			for (var row:int = 0; row < _guide.origRows; row++) {
				for (var col:int = 0; col < _guide.origCols; col++) {
					var fb:FlipBox = _gridCopy.shift()
					var bdata:BitmapData = new BitmapData(Math.ceil(_baseW * _scaleMultiplier), Math.ceil(_baseH * _scaleMultiplier), true, 0x00ffffff);
					
					var fbmp:Sprite = new Sprite();
					fbmp.graphics.clear();
					bdata.copyPixels(bmp, new Rectangle(sx, sy, (col || 1) * Math.ceil(_baseW * _scaleMultiplier), (row || 1) * Math.ceil(_baseH * _scaleMultiplier)), new Point(0, 0));
					fbmp.graphics.beginBitmapFill(bdata, null, false, true);
					fbmp.graphics.drawRect(0, 0, Math.ceil(_baseW * _scaleMultiplier), Math.ceil(_baseH * _scaleMultiplier));
					fbmp.graphics.endFill();
	
					if (fb.isFrontFacing) {
						fb.front = fbmp;
					}else {
						fb.back = fbmp;
					}
					_bmps.push(fbmp);
					
					sx += Math.ceil(_baseW * _scaleMultiplier);
				}
				sx = startx;
				sy += Math.ceil(_baseH * _scaleMultiplier);
			}
			_gridCopy = null;
			_bmps = null;
		}
		protected function onDetailedViewStarted(evt:GenericEvent):void {
			_onDetail = true;
			startDetailedChange(true);
		}
		protected function onDetailedViewReady(evt:GenericEvent):void {
			
			refreshGuideSlices();
		}
		public function set detailGuide(dg:ProductDetailedView):void {
			_detailsGuide = dg;
			_detailsGuide.addEventListener(GenericEvent.STARTED, onDetailedViewStarted);
			_detailsGuide.addEventListener(GenericEvent.READY, onDetailedViewReady);
		}
		public function set guide(dg:DisplayGrid):void {
			_guide = dg;
			_guide.addEventListener(GenericEvent.GENERATED, onGuideRendered);
			_guide.addEventListener(GenericEvent.PROGRESS, onGuideRenderProgress);
		}
		public function set baseWidth(n:Number):void {
			_baseW = n;
		}
		public function get baseWidth():Number {
			return _baseW;
		}
		public function set baseHeight(n:Number):void {
			_baseH = n;
		}
		public function get baseHeight():Number {
			return _baseH;
		}
	}
	
}